<?php

namespace Modules\Groupon\Entities;

use Modules\Core\Entities\BaseEntity as Model;
use Modules\Product\Entities\Sku;
use ThrowException;

class Groupon extends Model
{
    protected $guarded = [];
    protected $table = 'groupons';

    static public $resourceName = '拼团';

    protected $appends = ['union_status', 'union_status_text'];

    public function getUnionStatusAttribute()
    {
        $map = [
            0 => 'pending',
            1 => 'working',
            2 => 'closed'
        ];

        return $map[$this->status];
    }

    public function getUnionStatusTextAttribute()
    {
        $map = [
            'pending' => '未开始',
            'working' => '进行中',
            'closed' => '已结束',
        ];

        return @v($map[$this->union_status], '未知状态');
    }

    public function product()
    {
        return $this->belongsTo('\Modules\Product\Entities\Product');
    }

    public function skus()
    {
        return $this->hasMany('\Modules\Groupon\Entities\GrouponSku', 'groupon_id');
    }

    public function scopeValid($query)
    {
        return $query->where([
            ['status', '<>', 2],
            ['end_at', '>', now()],
            'is_displayed' => 1
        ]);
    }

    static public function beforeGetList($options)
    {
        if (isset($options['type']))
            $options['where']['type'] = $options['type'];

        return $options;
    }

    public function updateWith($info)
    {
        $product = $info['product'];

        $this->update([
            'timeout' => $info['timeout'],
            'need_member' => $info['need_member'],
            'start_at' => $info['start_at'],
            'end_at' => $info['end_at'],
            'purchase_limit' => $info['purchase_limit'],
            'price' => collect($product['skus'])->min('price'),
            'status' => strtotime($info['start_at']) > time() ? 0 : $this->status
        ]);


        foreach ($product['skus'] as $sku) {

            $sku = json_decode(json_encode($sku));

            $item = $this->skus()->where('sku_id', $sku->id)->first();

            if ($item)
                $item->update([
                    'selling_price' => $sku->price,
                    'is_join' => $sku->is_join,
                    'stock' => $sku->stock
                ]);
            else
                ThrowException::Conflict('sku 不正确');
        }

        $this->updateStockAndSales();
    }

    static public function createWithReq($req)
    {
        $product = $req->product;
        $item = Groupon::create([
            'uuid' => uniqid(),
            'product_id' => $product['id'],
            'type' => $req->type,
            'timeout' => $req->timeout,
            'need_member' => $req->need_member,
            'start_at' => $req->start_at,
            'end_at' => $req->end_at,
            'purchase_limit' => $req->purchase_limit,
            'price' => collect($product['skus'])->min('price'),
            'status' => strtotime($req->start_at) > time() ? 0 : 1
        ]);

        $skus = [];
        foreach ($product['skus'] as $sku) {
            $sku = json_decode(json_encode($sku));
            array_push($skus, [
                'uuid' => uniqid(),
                'sku_id' => $sku->id,
                'selling_price' => $sku->price,
                'stock' => $sku->stock,
                'is_join' => $sku->is_join,
            ]);

            // 相应减小SKU库存
            $skuItem = Sku::getEntity([
                'id' => $sku->id
            ]);
            $skuItem->reduceStock($sku->stock) ?: ThrowException::Conflict('库存不足');
        }

        $item->skus()->createMany($skus);

        $item->updateStockAndSales();

        return $item;
    }

    public function close($by, $reason = NULL)
    {
        foreach ($this->skus as $sku) {
            if ($sku->base_sku)
                $sku->base_sku->addStock($sku->stock);
        }

        $this->status = 2;
        $this->closed_at = now();
        $this->closed_by = $by;
        $this->save();
    }

    public function closeByTimeout()
    {
        $this->close(0);
    }

    public function updateStockAndSales()
    {
        $sales = 0;
        $stock = 0;

        foreach ($this->skus as $sku) {
            $sales += $sku->sales;
            $stock += $sku->stock;
        }

        $this->update([
            'stock' => $stock,
            'sales' => $sales
        ]);
    }
}
